﻿using System;
using System.Threading;
using System.Collections.Generic;
using System.Text;

namespace EnhSimGUI.Solver
{
    class SolveGA
    {
        protected int priorityCount;
        protected int populationSize;
        protected double mutationPercent;
        protected int matingPopulationSize;
        protected int favoredPopulationSize;
        protected int cutLength;
        protected int generation;
        protected Thread worker = null;
        protected bool started = false;
        protected String[] priorities;
        protected Chromosome[] chromosomes;

        public void Initialization(String[] list, int count)
        {
            Random randObj = new Random();
            priorities = (String[]) list.Clone();
            priorityCount = count;
            populationSize = 1000;
            mutationPercent = 0.05;
            matingPopulationSize = populationSize / 2;
            favoredPopulationSize = matingPopulationSize / 2;
            cutLength = priorityCount / 5;

            // create the initial chromosomes
            chromosomes = new Chromosome[populationSize];
            for (int i = 0; i < populationSize; i++)
            {
                chromosomes[i] = new Chromosome(priorities);
                chromosomes[i].assignCut(cutLength);
                chromosomes[i].assignMutation(mutationPercent);
            }
            Chromosome.sortChromosomes(chromosomes, populationSize);
            started = true;
            generation = 0;
        }

        public void TSPCompute()
        {
            double thisCost = 500.0;
            double oldCost = 0.0;
            double dcost = 500.0;
            int countSame = 0;
            Random randObj = new Random();
            while (countSame < 120)
            {
                generation++;
                int ioffset = matingPopulationSize;
                int mutated = 0;
                for (int i = 0; i < favoredPopulationSize; i++)
                {
                    Chromosome cmother = chromosomes[i];
                    int father = (int)(randObj.NextDouble() * (double)matingPopulationSize);
                    Chromosome cfather = chromosomes[father];
                    mutated += cmother.mate(cfather, chromosomes[ioffset], chromosomes[ioffset + 1]);
                    ioffset += 2;
                }
                for (int i = 0; i < matingPopulationSize; i++)
                {
                    chromosomes[i] = chromosomes[i + matingPopulationSize];
                    chromosomes[i].calculateCost(priorities);
                }
                // Now sort the new population
                Chromosome.sortChromosomes(chromosomes, matingPopulationSize);
                double cost = chromosomes[0].getCost();
                dcost = Math.Abs(cost - thisCost);
                thisCost = cost;
                double mutationRate = 100.0 * (double)mutated / (double)matingPopulationSize;
                System.Console.WriteLine("Generation = " + generation.ToString() + " Cost = " + thisCost.ToString() + " Mutated Rate = " + mutationRate.ToString() + "%");
                if ((int)thisCost == (int)oldCost)
                {
                    countSame++;
                }
                else
                {
                    countSame = 0;
                    oldCost = thisCost;
                    //System.Console.WriteLine("oldCost = " + oldCost.ToString());
                }
            }
            for (int i = 0; i < priorities.Length; i++)
            {
                chromosomes[i].PrintPriority(i, priorities);
            }
        }
    }
}
